import logging
import uuid
from dataclasses import asdict
from typing import Literal, Optional

from fastapi import APIRouter, BackgroundTasks, Depends, HTTPException
from pydantic import BaseModel

from src.globals import (
    ServiceContainer,
    ServiceMetadata,
    get_service_container,
    get_service_metadata,
)
from src.web.v1.services import Configuration, QuestionRecommendation

router = APIRouter()
logger = logging.getLogger("wren-ai-service")

"""
Question Recommendation Router

This router handles endpoints related to generating and retrieving question recommendations.

Endpoints:
1. POST /question-recommendations
   - Generates new question recommendations
   - Request body: PostRequest
     {
       "mdl": "{ ... }",                                 # JSON string of the MDL (Model Definition Language)
       "previous_questions": ["question1", "question2"], # Optional list of previous questions
       "project_id": "project-id",                       # Optional project ID
       "max_questions": 5,                               # Optional max number of questions to generate, defaults to 5
       "max_categories": 3,                              # Optional max number of categories, defaults to 3
       "regenerate": false,                              # Optional flag to force regeneration, defaults to false
       "configuration": {                                # Optional configuration settings
         "language": "English",                          # Optional language, defaults to "English"
         "timezone": {                                   # Optional timezone settings
           "name": "Asia/Taipei",                        # Timezone name, defaults to "Asia/Taipei"
         }
       }
     }
   - Response: PostResponse
     {
       "id": "unique-uuid"                               # Unique identifier for the generated recommendations
     }

2. GET /question-recommendations/{id}
   - Retrieves the status and result of question recommendations generation
   - Path parameter: id (str)
   - Response: GetResponse
     {
       "id": "unique-uuid",                      # Unique identifier of the recommendations
       "status": "generating" | "finished" | "failed",
       "response": {                             # Present only if status is "finished"
         "questions": [...]                      # List of question recommendations
       },
       "error": {                                # Present only if status is "failed"
         "code": "OTHERS" | "MDL_PARSE_ERROR" | "RESOURCE_NOT_FOUND",
         "message": "Error description"
       }
     }

The question recommendation generation is an asynchronous process. The POST endpoint
initiates the generation and returns immediately with an ID. The GET endpoint can
then be used to check the status and retrieve the result when it's ready.

Usage:
1. Send a POST request to start the generation process.
2. Use the returned ID to poll the GET endpoint until the status is "finished" or "failed".

Note: The actual generation is performed in the background using FastAPI's BackgroundTasks.
"""


class PostRequest(BaseModel):
    mdl: Optional[str] = "{}"  # 使mdl字段可选，默认为空JSON对象
    previous_questions: list[str] = []
    project_id: Optional[str] = None
    max_questions: Optional[int] = 5
    max_categories: Optional[int] = 3
    regenerate: Optional[bool] = False
    configuration: Optional[Configuration] = Configuration()


class PostResponse(BaseModel):
    id: str


@router.post(
    "/question-recommendations",
    response_model=PostResponse,
)
async def recommend(
    request: PostRequest,
    background_tasks: BackgroundTasks,
    service_container: ServiceContainer = Depends(get_service_container),
    service_metadata: ServiceMetadata = Depends(get_service_metadata),
) -> PostResponse:
    try:
        id = str(uuid.uuid4())
        service = service_container.question_recommendation

        # 记录接收到的请求详情
        logger.info(
            f"收到问题推荐请求: id={id}, 包含 {len(request.previous_questions)} 个历史问题"
        )

        # 检查mdl是否为有效的JSON字符串
        if request.mdl != "{}":
            try:
                import json

                json.loads(request.mdl)
            except json.JSONDecodeError as e:
                logger.warning(f"提供的MDL不是有效的JSON格式: {e}")
                # 使用空的JSON对象作为替代
                request.mdl = "{}"

        service[id] = QuestionRecommendation.Resource(id=id)
        input = QuestionRecommendation.Input(
            id=id,
            mdl=request.mdl,
            previous_questions=request.previous_questions,
            project_id=request.project_id,
            max_questions=request.max_questions,
            max_categories=request.max_categories,
            regenerate=request.regenerate,
            configuration=request.configuration,
        )

        logger.info(f"开始后台生成问题推荐: id={id}")
        background_tasks.add_task(
            service.recommend, input, service_metadata=asdict(service_metadata)
        )

        return PostResponse(id=id)
    except Exception as e:
        logger.error(f"生成问题推荐时发生错误: {str(e)}")
        raise HTTPException(status_code=500, detail=f"处理请求时出错: {str(e)}")


class GetResponse(BaseModel):
    id: str
    status: Literal["generating", "finished", "failed"]
    response: Optional[dict]
    error: Optional[dict]
    trace_id: Optional[str] = None


@router.get(
    "/question-recommendations/{id}",
    response_model=GetResponse,
)
async def get(
    id: str,
    service_container: ServiceContainer = Depends(get_service_container),
) -> GetResponse:
    try:
        resource = service_container.question_recommendation[id]

        def _formatter(response: dict) -> dict:
            # 检查response是否有效
            if not response or not isinstance(response, dict):
                return {"questions": []}

            # 检查questions的格式
            questions_data = response.get("questions", [])

            # 如果questions已经是列表，直接返回
            if isinstance(questions_data, list):
                return {"questions": questions_data}

            # 如果questions是字典，按原来的逻辑处理
            if isinstance(questions_data, dict):
                questions = []
                for category, category_questions in questions_data.items():
                    if isinstance(category_questions, list):
                        for question in category_questions:
                            if isinstance(question, dict):
                                questions.append(question)
                return {"questions": questions}

            # 默认返回空列表
            return {"questions": []}

        return GetResponse(
            id=resource.id,
            status=resource.status,
            response=_formatter(resource.response),
            error=resource.error and resource.error.model_dump(),
            trace_id=resource.trace_id,
        )
    except Exception as e:
        # 记录错误并返回一个默认响应
        logger.error(f"Error retrieving question recommendation with ID {id}: {str(e)}")
        return GetResponse(
            id=id,
            status="failed",
            response={"questions": []},
            error={
                "code": "RESOURCE_NOT_FOUND",
                "message": f"Resource with ID {id} not found or error occurred: {str(e)}",
            },
        )


# class RecommendationRequest(BaseModel):
#     mdl: str
#     previous_questions: list


# @router.post("/recommendations")
# async def get_recommendations(request: RecommendationRequest):
#     logger.info("Received recommendation request: %s", request)
#     try:
#         recommendations = await QuestionRecommendation(request.mdl, request.previous_questions)
#         logger.info("Recommendations generated successfully: %s", recommendations)
#         return recommendations
#     except Exception as e:
#         logger.error("Error generating recommendations: %s", str(e))
#         raise HTTPException(status_code=500, detail="Failed to generate recommendations")
